//
//  GameViewController.m
//  CandyCrushClone
//
//  Created by  Stefan Nestorov on 12/29/14.
//  Copyright (c) 2014 Nestorov Engineering. All rights reserved.
//

#import "RWTViewController.h"
#import "RWTMyScene.h"
#import "RWTLevel.h"
#import "RWTSwap.h"
#import "CommunicationManager.h"
#import "GameInfo.h"
#import "AvatarView.h"
#import "AudioController.h"
#import "Tracker.h"

@interface RWTViewController () <CommunicationDelegate, SceneDelegate> {
    
    CommunicationManager* _communicationManager;
    id _beginGameObserver;
    id _receivedResponseObserver;
    id _forcedGameOverObserver;
}

@property (strong, nonatomic) RWTLevel *level;
@property (strong, nonatomic) RWTMyScene *scene;
@property (assign, nonatomic) BOOL shoudGetTUC;
@property (weak, nonatomic) IBOutlet UIView *waitingScreenView;
@property (weak, nonatomic) IBOutlet AvatarView *localPlayerAvatarView;
@property (weak, nonatomic) IBOutlet AvatarView *otherPlayerAvatarView;
@property (weak, nonatomic) IBOutlet UIImageView *searchingForOpponentImageView;
@property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
@property (weak, nonatomic) IBOutlet SKView *sceneView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *sceneBottomConstraint;

@end


@implementation RWTViewController

- (void)viewDidLoad
{
    
    [super viewDidLoad];
    
    //Init communicaiton manager
    _communicationManager = [CommunicationManager sharedManager];
    [_communicationManager setCommunicationDelegate:self];
    
    [self initNewGameScene];
    [self resetParameters];
    
    __weak RWTViewController *weakSelf = self;
    
    // call beginGame from notification
    _beginGameObserver = [[NSNotificationCenter defaultCenter] addObserverForName:BEGIN_GAME object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        
        [weakSelf foundOpponent];
        
        [weakSelf delayAfter:2 completion:^{
            
            // Let's start the game!
            [weakSelf beginGame];
            
            [UIView animateWithDuration:1 animations:^{
                
                weakSelf.waitingScreenView.alpha = 0;
                
            }];
            
        }];
        
    }];
    
    // called when is Received mine Move response from Server
    _receivedResponseObserver = [[NSNotificationCenter defaultCenter] addObserverForName:RECEIVED_RESPONSE object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        
        // if there was Internet delay (lag), continue normal execution
        if ( weakSelf.shoudGetTUC == YES ) {
            
            weakSelf.shoudGetTUC = NO;
            NSArray *columns = [weakSelf.level topUpCookies];
            [weakSelf.scene animateNewCookies:columns completion:^{
                
                [weakSelf.scene playHeroAnimationIfNecessary];
                
//                [_level printCookies];
                
                [weakSelf handleMatches];
            }];
        }
        
    }];
    
    _forcedGameOverObserver = [[NSNotificationCenter defaultCenter] addObserverForName:CMD_FORCED_GAME_OVER object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        
        [weakSelf checkForGameEnd];
        
    }];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterForeground) name:CLEAN_SCENE object:NULL];
    
}


-(void)viewWillAppear:(BOOL)animated
{
    
    [super viewWillAppear:animated];
    
    [[AudioController sharedInstance] stopBGMusic];
    
}


-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    [self searchForOpponent];
    
}


-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[NSNotificationCenter defaultCenter] removeObserver:_receivedResponseObserver];
    [[NSNotificationCenter defaultCenter] removeObserver:_beginGameObserver];
    [[NSNotificationCenter defaultCenter] removeObserver:_forcedGameOverObserver];
    
    _receivedResponseObserver = nil;
    _beginGameObserver = nil;
    _forcedGameOverObserver = nil;
    
}


- (void)initNewGameScene
{
    
    // Configure the view.
    SKView *skView = _sceneView; //  (SKView *)self.view;
    skView.multipleTouchEnabled = NO;
    
    // Create and configure the scene.
    self.scene = [RWTMyScene sceneWithSize:CGSizeMake(320, 568)];
    self.scene.scaleMode = SKSceneScaleModeAspectFill;
    self.scene.sceneDelegate = self;
    
    // Detect 3.5 inch display
    if ( SCREEN_MAX_LENGTH < 568.0 ) {
        
        _sceneBottomConstraint.constant = -8;
        [self.scene adjustSceneForSmallDisplay];
        
    }
    
    // Load the level.
    self.level = [[RWTLevel alloc] initWithFile:@"Level_0"];
    
    // set level as Adapter delegate
    [LevelAdapter sharedAdapter].delegate = self.level;
    
    self.scene.level = self.level;
//    [self.scene addTiles];
    
    _shoudGetTUC = NO;
    
    __weak RWTViewController *weakSelf = self;
    
    id block = ^(RWTSwap *swap, BOOL isSimulation) {
        weakSelf.scene.canMakeMove = NO;
        
        if ([weakSelf.level isPossibleSwap:swap]) {
            
            // Bug occurred
            if ( swap.cookieA.sprite == nil || swap.cookieB.sprite == nil ) {
                
                NSLog(@"PossibleSwap BUG !");
                [weakSelf handleMatches];
                
                return;
            }
            
            [weakSelf.level performSwap:swap isSimulation:isSimulation];
            [weakSelf.scene animateSwap:swap completion:^{
                [weakSelf handleMatches];
                
            }];
            
        } else {
            
            // Bug occurred
            if ( swap.cookieA.sprite == nil || swap.cookieB.sprite == nil ) {
                
                NSLog(@"InvalidSwap BUG !");
                [weakSelf handleMatches];
                
                return;
            }
            
            [weakSelf.scene animateInvalidSwap:swap completion:^{
                [weakSelf handleMatches];
//                weakSelf.view.userInteractionEnabled = YES;
            }];
        }
        
    };
    
    self.scene.swipeHandler = block;
    
    // Present the scene.
    [skView presentScene:self.scene];
    
}


- (void)resetParameters
{
    
    UIImageView *flashImageView = (UIImageView *)[_waitingScreenView viewWithTag:11];
    [flashImageView removeFromSuperview];
    flashImageView = nil;
    
    [self resetAvatarViews];
    
    // Reset GameInfo params
    [[GameInfo sharedInfo] resetGameParameters];
    [[GameInfo sharedInfo] setIsAbortedGameByMe:NO];
    
    _waitingScreenView.alpha = 1;
    _searchingForOpponentImageView.alpha = 0;
    
}


- (void)resetAvatarViews
{
    
    CGRect localPlayerAvatarFrame = _localPlayerAvatarView.frame;
    localPlayerAvatarFrame.origin.y = self.view.frame.size.height/2 - localPlayerAvatarFrame.size.height/2;
    
    CGRect otherPlayerAvatarFrame = _otherPlayerAvatarView.frame;
    otherPlayerAvatarFrame.origin.y = self.view.frame.size.height/2 - otherPlayerAvatarFrame.size.height/2;
    
    [_localPlayerAvatarView removeFromSuperview];
    _localPlayerAvatarView = nil;
    
    [_otherPlayerAvatarView removeFromSuperview];
    _otherPlayerAvatarView = nil;
    
    AvatarView *localAvatar = [[AvatarView alloc] init];
    _localPlayerAvatarView = localAvatar;
    [_localPlayerAvatarView setFrame:localPlayerAvatarFrame];
    [_waitingScreenView addSubview:_localPlayerAvatarView];
    
    AvatarView *otherAvatar = [[AvatarView alloc] init];
    _otherPlayerAvatarView = otherAvatar;
    [_otherPlayerAvatarView setFrame:otherPlayerAvatarFrame];
    [_waitingScreenView addSubview:_otherPlayerAvatarView];
    
    [self initAvatars];
    
}


- (void)initAvatars
{
    
    NSString *localPlayerName = [[NSUserDefaults standardUserDefaults] objectForKey:USERNAME_KEY];
    UIColor *localPlayerTextColor = [UIColor colorWithRed:1.0/255.0 green:116.0/255.0 blue:1.0/255.0 alpha:1];
    [_localPlayerAvatarView setName:localPlayerName withColor:localPlayerTextColor];
    
    NSString *avatarImageName = [NSString stringWithFormat:@"animal_%zd",[GameInfo sharedInfo].localPlayer.hero.type];
    [_localPlayerAvatarView setImage:[UIImage imageNamed:avatarImageName] forLocalPlayer:YES];
    
    UIColor *localPlayerStrokeColor = [UIColor colorWithRed:88.0/255.0 green:201.0/255.0 blue:1.0/255.0 alpha:1];
    UIColor *localPlayerFillColor = [UIColor colorWithRed:179.0/255.0 green:237.0/255.0 blue:80.0/255.0 alpha:1];
    [_localPlayerAvatarView setCircleLayerStrokeColor:localPlayerStrokeColor andFillColor:localPlayerFillColor];
    
    UIColor *otherPlayerStrokeColor = [UIColor colorWithRed:231.0/255.0 green:104.0/255.0 blue:36.0/255.0 alpha:1];
    UIColor *otherPlayerFillColor = [UIColor colorWithRed:251.0/255.0 green:173.0/255.0 blue:43.0/255.0 alpha:1];
    [_otherPlayerAvatarView setCircleLayerStrokeColor:otherPlayerStrokeColor andFillColor:otherPlayerFillColor];
    
}


- (void)searchForOpponent
{
    
    [self processGameType];
    [[GameInfo sharedInfo] setIsAbortedGameByMe:NO];
    
    // Show searchingForOpponent image
    [UIView animateWithDuration:0.5f animations:^{
        _searchingForOpponentImageView.alpha = 1;
    }];
    
    [self playStarsAnimation];
    
    CGFloat bounceXOffset = 48;
    CGPoint leftBouncePoint = CGPointMake(160 + bounceXOffset, _localPlayerAvatarView.center.y);
    CGPoint rightBouncePoint = CGPointMake(160 - bounceXOffset, _localPlayerAvatarView.center.y);
    [_localPlayerAvatarView bounceOffPoint:rightBouncePoint morphSize:CGSizeMake(75, 100)];
    [_otherPlayerAvatarView bounceOffPoint:leftBouncePoint morphSize:CGSizeMake(75, 100)];
    
    [[AudioController sharedInstance] playEffect:kSearchingSound];
    
}


- (void)foundOpponent
{
    
    // Hide searchingForOpponent image
    [UIView animateWithDuration:0.5f animations:^{
        _searchingForOpponentImageView.alpha = 0;
    }];
    
    // Stop Animating stars
    [_backgroundImageView stopAnimating];
    [_backgroundImageView setImage:_backgroundImageView.animationImages[3]];
    
    // Make Avatars to square
    _localPlayerAvatarView.shouldTransitionToFinishedState = YES;
    _otherPlayerAvatarView.shouldTransitionToFinishedState = YES;
    
    NSString *avatarImageName = [NSString stringWithFormat:@"animal_%zd",[GameInfo sharedInfo].otherPlayer.hero.type];
    [_otherPlayerAvatarView setImage:[UIImage imageNamed:avatarImageName] forLocalPlayer:NO];
    
    NSString *otherPlayerName = [GameInfo sharedInfo].otherPlayer.name;
    UIColor *otherPlayerTextColor = [UIColor colorWithRed:229.0/255.0 green:14.0/255.0 blue:1.0/255.0 alpha:1];
    [_otherPlayerAvatarView setName:otherPlayerName withColor:otherPlayerTextColor];
    
    NSString *localPlayerName = [GameInfo sharedInfo].localPlayer.name;
    UIColor *localPlayerTextColor = [UIColor colorWithRed:1.0/255.0 green:116.0/255.0 blue:1.0/255.0 alpha:1];
    [_localPlayerAvatarView setName:localPlayerName withColor:localPlayerTextColor];
    
    [self playFlashAnimation];
    
    [Tracker trackEvent:@"Start Game" withParams:nil];
    
}


#pragma mark - Animations

- (void)playFlashAnimation
{
    
    [[AudioController sharedInstance] playEffect:kShowFlashSound];
    
    UIImageView *flashImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"flashImage"]];
    flashImageView.center = _waitingScreenView.center;
    flashImageView.tag = 11;
    [_waitingScreenView addSubview:flashImageView];
    
    // Make it invisible and small
    flashImageView.alpha = 0;
    flashImageView.transform = CGAffineTransformMakeScale(0.1, 0.1);
    
    // Make it visible
    [UIView animateWithDuration:0.5 animations:^{
        
        flashImageView.alpha = 1;
        
    }];
    
    // Scale the normal
    [UIView animateWithDuration:2 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:10 options:kNilOptions animations:^{
        
        flashImageView.transform = CGAffineTransformMakeScale(1.0, 1.0);
        
    } completion:nil];
    
}


- (void)playStarsAnimation
{
    
    NSMutableArray *images = [[NSMutableArray alloc] init];
    
    // From 1 to 4 = 4 images
    for (int i = 1; i <= 4; i++) {
        [images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"starsBackground_%d", i]]];
    }
    
    // From 3 to 1 = 3 images
    for (int i = 3; i >= 1; i--) {
        [images addObject:[UIImage imageNamed:[NSString stringWithFormat:@"starsBackground_%d", i]]];
    }
    
    _backgroundImageView.animationImages = images;
    _backgroundImageView.animationDuration = 2.1f; // this is the duration of AvatarView animation
    _backgroundImageView.animationRepeatCount = 0;
    [_backgroundImageView startAnimating];
    
}


- (BOOL)shouldAutorotate
{
    return YES;
}

- (void)beginGame
{
    
    [self.scene updateLabels];
    [self.scene animateBeginGame];
    
    [self.scene removeAllCookieSprites];

    NSSet *newCookies = [self.level shuffle];
    [self.scene performSelector:@selector(addSpritesForCookies:) withObject:newCookies afterDelay:0.25];
    
}

- (void)shuffle
{
    
    [self.scene playShuffleImageAnimation];
    [self.scene removeAllCookieSprites];
    
    NSSet *newCookies = [self.level shuffle];
    [self.scene performSelector:@selector(addSpritesForCookies:) withObject:newCookies afterDelay:0.7];
    
}


- (void)resetTimerAndShouldShowHint:(BOOL)shouldShowHint additionalDelay:(float)delay
{
    
    [self.scene resetTimerAndShouldShowHint:shouldShowHint additionalDelay:delay];
    
}

#pragma mark - Handle matches

- (void)handleMatches
{
    
    __weak RWTViewController *weakSelf = self;
    
    NSSet *chains = [weakSelf.level removeMatches];
    
    if ( [chains count] == 0 ) {
        
        // set the counters for cookies with server values to prevent manipulation!
        [[GameInfo sharedInfo].localPlayer setCounterValuesFromServer];
        [[GameInfo sharedInfo].otherPlayer setCounterValuesFromServer];
        [weakSelf.scene updateLabels];
        [weakSelf checkForGameEnd];
        [weakSelf setCurrentBoardFromServer];
        [weakSelf shuffleIfNecessary];
        
        [weakSelf beginNextTurn];
        
        return;
    }
    
    [weakSelf.scene animateMatchedCookies:chains completion:^{

//        [weakSelf.scene updateLabels];
        
        NSArray *columns = [weakSelf.level fillHoles];
        
        [weakSelf.scene animateFallingCookies:columns completion:^{
            
            NSArray *columns = [weakSelf.level topUpCookies];
            
            if ( columns == nil ) {
                
                // there is Internet delay (lag), so wait for response from server
                NSLog(@"Recieved Nil topUpCookies array !!");
                weakSelf.shoudGetTUC = YES;
                return;
            }
            
            [weakSelf.scene animateNewCookies:columns completion:^{
                
                [weakSelf.scene playHeroAnimationIfNecessary];
//                [_level printCookies];
                
                [weakSelf handleMatches];
            }];
            
        }];
        
    }];
    
}


- (void)checkForGameEnd
{
    
    // Only reset GameParameters if localPlayer aborted the game
    if ( [GameInfo sharedInfo].isAbortedGameByMe == YES ) {
        
        [[GameInfo sharedInfo] resetGameParameters];
        
        return;
        
    }
    
    // GAME OVER
    if ( [GameInfo sharedInfo].isGameOver == YES ) {
        
        [[GameInfo sharedInfo] resetGameParameters];
        
        [self.scene animateGameOver];
        [self trackGameOver];
        
    }
    
}


- (void)beginNextTurn
{
    
    [self.level detectPossibleSwaps];
    self.scene.canMakeMove = YES;
    
}


- (void)shuffleIfNecessary
{
    
    if ( [GameInfo sharedInfo].shuffleCookiesSet != nil ) {

        [self shuffle];
        
    }
    
}


- (void)setCurrentBoardFromServer
{
    
    // do Not set currentBoard if there is Shuffle
    if ( [GameInfo sharedInfo].shuffleCookiesSet != nil ) {
        return;
    }
    
    NSSet *newBoard = [_level getCurrentBoardFromServerIfNecessary];
    NSLog(@"### newBoard: %@",newBoard);
    
    // change Cookie Sprites in Scene if there is newBoard
    if ( [newBoard count] > 0 ) {
        [self.scene addSpritesForCookiesFromServer:newBoard];
    }
    
}


- (void)abortGame
{
    
    [Tracker trackEvent:@"Abort Game" withParams:nil];
    [[GameInfo sharedInfo] resetGameParameters];
    [[GameInfo sharedInfo] setIsAbortedGameByMe:YES];
    
    [_communicationManager sendReturnToLobbyRequest];
    
    [self.navigationController popViewControllerAnimated:YES];
    
}


- (void)didEnterForeground
{
    
    _communicationManager.isInGame = NO;
    [_communicationManager sendReturnToLobbyRequest];
    
    NSLog(@"%s", __FUNCTION__);

    if ( self.scene != nil ) {
        
        [self.scene cleanScene];
        
    }
    
    [self.navigationController popViewControllerAnimated:YES];
    
}


- (void)startNewGame
{
    
    // If conenction was lost return to MainVC to reconnect
    if ( _communicationManager.isConnected == NO ) {
        [self didEnterForeground];
        return;
    }
    
    __weak RWTViewController *weakSelf = self;
    
    [weakSelf resetParameters];
    [weakSelf searchForOpponent];
    
    _waitingScreenView.alpha = 0.25;
    
    // Show waitingScreen
    [UIView animateWithDuration:0.25 animations:^{
        
        weakSelf.waitingScreenView.alpha = 1;
        
    } completion:^(BOOL finished) {
        
        [weakSelf.scene cleanScene];
        [weakSelf initNewGameScene];
        
    }];
    
}


// Determines what to do for particular GameType
-(void)processGameType
{
    
    switch ( _gameType ) {
            
        case QUICK_GAME:
            // Join me to Waiting List
            [_communicationManager sendJoinToWaitingListRequest];
            break;
            
        case FRIENDS_GAME:
            // configure game from Friend Game Inviation
            NSLog(@"GameType: FRIENDS_GAME");
            break;
            
        default:
            NSLog(@"GameType was NOT processed");
            break;
    }
    
}


- (BOOL)prefersStatusBarHidden
{
    return YES;
}


// Util delay function
- (void)delayAfter:(CGFloat)seconds completion:(void (^)())completion
{
    
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC);
    
    dispatch_after(popTime, dispatch_get_main_queue(), ^{
        completion();
    });
    
}


- (void)trackGameOver
{
    
    NSString *didWin = [GameInfo sharedInfo].winnerID == [GameInfo sharedInfo].localPlayer.playerId ? @"Yes" : @"No";
    
    [Tracker trackEvent:@"Game Over" withParams:@{
                                                  @"Did win" : didWin,
                                                  }];
    
}


-(void)dealloc
{
    
    NSLog(@"Dealloc: %@",[self class]);
    
}


@end
